// var a;
// 第一句js代码
// console.log("hello world!");
// console.log("hello world!");
// console.log("hello world!");
// console.log("hello world!");
// console.log("hello world!");
// console.log("hello world!");
// 打印输出括号里面的内容

// 一、如何运行js代码：
// 1.使用浏览器运行js代码，需要通过html文件引入js代码，然后浏览器就可以运行js代码
// 2.使用cmd运行（node）js代码
//   （1）进入到js文件所在的文件夹目录
//       换盘：d:+回车  
//       进入文件夹：cd 文件夹名称+回车
//       返回上一级文件夹：cd.. +回车
//   （2）运行js文件： node js文件名
// 3.使用vscode终端运行（node）js代码
//   (1)选中要运行的js文件，点击鼠标右键，选择在终端中打开
//  （2）运行js文件：node js文件名
//   (3)清屏：cls

// 二、NPM:下载项目所需的代码模块的工具
{
    // 用户输入两个数字，求两个数字的乘积
    // let readline = require("readline-sync");
    // let:表示声明变量的一种方式
    // readline：是一个程序员自己定义的变量名，用于接受引入的模块
    // require：表示引入模块
    // readline-sync：输入模块的名称
    // console.log("请输入第一个数字：");
    // 提示信息，提醒用户输入数字
    // let num1 = readline.question("");
    // num1:是一个程序员自己定义的变量名，用于接受用户输入的数字
    // console.log("请输入第二个数字：");
    // 提示信息，提醒用户输入数字
    // let num2 = readline.question("");
    // 声明一个变量num2,来接受用户输入的数字
    // console.log(num1 * num2);
    // 输出乘积结果
}


// 使用npm下载输入模块：npm install readline-sync
// 注意：1.代码模块仅限于当前项目文件夹使用，若其他项目文件夹需要，就必须重新下载模块
//      2.npm是从国外的服务器下载模块
// 安装淘宝镜像：是指把国外服务器上的内容间隔制定的时间，完全复制到国内淘宝服务器上
// npm install -g cnpm --registry=http://registry.npmmirror.com
// 注意：安装淘宝镜像因为是全局安装，所以只用安装一次

// 使用cnpm下载输入模块：cnpm install readline-sync


// 三、取变量名的硬性要求
// 1.可以包含数字、字母、美元符号、下划线，但是不能有其他特殊符号
// 2.不能以数字开头
// 3.严格区分大小写
// 4.不能用js里面的关键字和保留字作为变量名
// a1_$2=90;
// A1_$2=90;

// test=89;

// 四、js数据分类
// 1.简单数据类型：string҅ symbol҅ number҅ boolean҅ undefined҅ null
// 2.复杂数据类型：object

// 五、查看数据类型：typeof运算符
// console.log(typeof 45);//number
// console.log(typeof "45");//string

// 六、声明变量的几种方式
// 1.let(ES6新增)
// 特点：相同变量名不能重复声明;声明的变量值可以任意修改
// let a;//声明变量，但是没有给初始值;默认值是undefined
// console.log(a);//undefined
// let b=10;//声明变量，同时给初始值
// console.log(b);//10
// a=10;
// console.log(a);//10

// let n=10;
// let m=20;
// 简写为
// let n=10,m=20;

// 2.const(ES6新增):声明常量
// 特点：声明的常量，变量必须有初始值；声明的变量如果是简单数据类型，值不能修改；相同变量名不能重复声明
// const x=9;
// console.log(x);

// 3.var
// 特点：相同变量名可以重复声明;相同变量名重复声明，后面的值覆盖前面的值；变量的值可以任意修改
// var z;//声明变量，但是没有给初始值;默认值是undefined
// console.log(z);//undefined
// var z=20;
// console.log(z);//20
// var z=30;
// console.log(z);//30
// z=66;
// console.log(z);

// 4.遗漏声明:相当于var声明；遗漏声明变量一定要给初始值
// y=55;
// console.log(y);//55


// 七、作用域
// （一）全局作用域：一进入js文件的环境就是全局作用域，在全局作用域里面声明的变量就是全局变量
// （二）局部作用域：大括号内部环境就是局部作用域，在局部作用域里面声明的变量就是局部变量
// 全局变量和局部变量的使用特点
// 1.全局变量可以在任何地方访问
// 2.局部变量只能用于局部作用域，全局无法访问局部变量  (局部作用域可以访问全局变量，全局作用域不能访问局部变量)
// 3.局部变量和全局变量名相同时，不冲突，在局部作用域中优先使用局部变量
// 4.使用var声明的变量都是全局变量
// 5.遗漏声明的变量相当于var声明的变量，也都是全局变量

// let a=10;//全局变量
// console.log(a);
// {
//     let b=20;//局部变量
//     let a=30;//局部变量，和全局变量不冲突，优先访问局部变量
//     console.log(a);//30
//     console.log(b);
//     var x=88;//全局变量
//     y=99;
// }
// console.log(a);//10
// // console.log(b);//b is not defined
// console.log(x);//88
// console.log(y);//99

// 八、变量提升:只有使用var声明的变量有变量提升，会把变量声明的部分提升到当前作用域的最顶端
// 注意：遗漏声明没有变量提升
// console.log(a);//undefined
// var a=10;
// console.log(a);//10
// console.log(b);
// b=20;


// 练习：
// let a = 4;//全局变量
// b = 5;//全局变量
// // console.log(s);//报错
// console.log(x);//undefined 
// {
//     s = 89;//全局变量
//     let a = 10;//局部变量
//     var x = 9;//全局变量 变量提升
//     let y = 55;//局部变量
//     console.log(a);//10
//     console.log(b);//5
//     console.log(s);//89
//     console.log(x);//9
//     console.log(y);//55
// }
// console.log(a);//4
// console.log(b);//5
// console.log(s);//89
// console.log(x);//9
// console.log(y);//报错

// 九、简单数据类型
// （一）undefined类型：该类型只有一个值，就是undefined本身；声明变量但是没有赋值的时候，默认值就是undefined
// let x;
// console.log(x);//undefined  表示值
// console.log(typeof x);//undefined 表示数据类型

// （二）null类型：该类型只有一个值，就是null本身，表示一个空对象
// 注意：undefined是由null派生而来，因此undefined==null

// =:赋值，把等号右边的值付给等号左边，等号左边必须是变量
// ==:相等，值相等
// ===：全等，数据类型和值都相等

// 简单数据类型和复杂数据类型的本质区别：在运行内存中存储的位置不同
// 简单数据类型存放在栈空间
// 复杂数据类型值存放在堆空间，地址存放在栈空间
// let a=10;
// let c=a;
// console.log(c);
// c=20;
// console.log(c,a);

// let obj={
//     name:"小米",
//     age:18
// }
// let xyz=obj;
// xyz.name="小红";
// console.log(xyz,obj);

// （三）boolean类型：该类型只有两个值，就是true和false，注意只是小写的
// 其他类型转成boolean类型的方法：
// 1.Boolean(数据)
// 2. !!+数据

// 只有9个数据转成布尔值是false，其他的都是true
// ""、''、``、undefined、null、0、-0、NaN、false

// console.log(Boolean(12));//true
// console.log(Boolean("hello world"));//true
// console.log(Boolean(1));//true
// console.log(Boolean(0));//false
// console.log(Boolean(-0));//false
// console.log(Boolean(""));//false
// console.log(Boolean(''));//false
// console.log(Boolean(``));//false
// console.log(Boolean(undefined));//false
// console.log(Boolean(null));//false
// console.log(Boolean(NaN));//false
// console.log(Boolean(false));//false

// console.log(!!123);//true

// (四)number类型:整数、实数、NaN

// console.log(9.12e+2);//912  9.12*10^2=912
// console.log(9.12e-2);//0.0912  9.12*10^-2=9.12*0.1=0.0912

// console.log(Number.MAX_VALUE);//1.7976931348623157e+308
// console.log(Number.MIN_VALUE);//5e-324
// console.log(Number.MIN_VALUE>0);//true

// let i=Math.pow(2,3);//8  2^3=8
// console.log(i);

// // NaN:非数值，本来应该返回数值，但是没有办法返回数字，为了避免抛出错误，就返回NaN
// // NaN的特点：任何涉及NaN的操作都会返回NaN;NaN和任何只都不相等，包括它本身
// console.log(10*"xyz");//NaN
// console.log(NaN+2);//NaN
// console.log(NaN==NaN);//false
// // isNaN(数据)：判断一个数据是否不是数值，是数值返回false，不是数值返回true
// // 注意：isNaN函数在接受到一个数据后，会尝试将数据转为数字(本质就是使用Number函数方法转数字)，可以转成数值的就当做数值看待
// console.log(isNaN(2));//false
// console.log(isNaN("hello"));//true
// console.log(isNaN("2"));//false  "2"=>2

// // 其他类型转成数字类型的方法
// // 1.Number(数据)
// console.log(Number(undefined));//NaN
// console.log(Number(null));//0
// console.log(Number(true));//1
// console.log(Number(false));//0
// console.log(Number(""));//0 
// console.log(Number("123"));//123  纯数字的字符串转成数字
// console.log(Number("123hello"));//NaN  不是纯数字的字符串转为NaN

// // 2.parseInt(数据)
// console.log(parseInt(undefined));//NaN
// console.log(parseInt(null));//NaN
// console.log(parseInt(true));//NaN
// console.log(parseInt(false));//NaN
// console.log(parseInt(""));//NaN
// console.log(parseInt("123"));//123 纯数字的字符串转成数字
// console.log(parseInt("123hello"));//123 尽可能多的保留数字
// console.log(parseInt("123hello456"));//123 尽可能多的保留数字
// console.log(parseInt("123.45"));//123 保留整数
// console.log(parseInt("123.95"));//123 保留整数

// // 3.parseFloat(数据)
// console.log(parseFloat(undefined));//NaN
// console.log(parseFloat(null));//NaN
// console.log(parseFloat(true));//NaN
// console.log(parseFloat(false));//NaN
// console.log(parseFloat(""));//NaN
// console.log(parseFloat("123"));//123 纯数字的字符串转成数字
// console.log(parseFloat("123hello"));//123 尽可能多的保留数字
// console.log(parseFloat("123hello456"));//123 尽可能多的保留数字
// console.log(parseFloat("123.45"));//123.45 保留小数
// console.log(parseFloat("123.95"));//123.95 保留小数

// // 4.数据*1 或者 数据/1
// console.log("hello"*1);//NaN
// // "hello"相当于使用Number函数转成数字  Number("hello")=NaN
// console.log("123"*1);//123  Number("123")=123
// console.log(""*1);//0  Number("")=0

// // 数据.toFixed(要保留的小数位数)
// console.log(123.456.toFixed(2));//123.46  默认四舍五入

// （五）string类型
// // 字符串就是使用引号包裹的数据
// console.log("hello world");
// console.log('hello "成都"');
// console.log("hello '成都'");
// console.log("hello \"成都\" ");  //  \:转义字符，就是把有特殊作用的符号转化为普通字符

// // 特点：字符串类型和任意类型相加都会转为字符串类型
// console.log(3+"hello");//3hello  字符串拼接
// console.log(undefined+"hello");//undefinedhello  字符串拼接
// console.log(NaN+"hello");//NaNhello  字符串拼接
// let num1=2;
// let num2=3;
// console.log(num1+"*"+num2+"="+num1*num2);//2*3=6

// 其他类型转字符串类型的方法：
// 1.数据.toString()：除了undefined和null，可以把其他类型转成字符串类型

// 2.String(数据)：都可以把其他类型转成字符串类型
// 3.数据+空字符串
// let n=undefined;
// console.log(typeof n);//undefined类型
// n=n+"";
// console.log(typeof n);//string类型

// ``:反引号（字符串模版）
// 特点：1.反引号里面的内容可以换行
//      2.反引号里面可以插入多个变量
let city="北京";
let a=10,b=20;
let x=`hello 
                               ${city}  ${a*b}`;
console.log(x);

console.log(`${a}*${b}=${a*b}`);

// 十、类型转化
// （一）、隐形转换
console.log("hello"*10);//"hello"转成NaN  
console.log(10%3);//1  %:表示取余数
console.log(10%2);//0  %:表示取余数